﻿using System;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;

namespace O1.Kernel
{
    [ContractVerification(true)]
    internal static class EdgeExtensions
    {
        public static Guid ToFingerprint(this Edge edge, CellAddress startVertex)
        {
            Contract.Requires(edge != null);

            return new Fingerprint(edge, startVertex).Value;
        }

        [StructLayout(LayoutKind.Explicit)]
        private struct Fingerprint
        {
            [FieldOffset(0)]
            public readonly Guid Value;

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Union struct. Value is used.")]
            [FieldOffset(0)]
            private readonly int startCellId;

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Union struct. Value is used.")]
            [FieldOffset(4)]
            private readonly int endcellId;

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Union struct. Value is used.")]
            [FieldOffset(8)]
            private readonly int edgeType;

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Union struct. Value is used.")]
            [FieldOffset(12)]
            private readonly short startTrunkId;

            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "Union struct. Value is used.")]
            [FieldOffset(14)]
            private readonly short endTrunkId;

            public Fingerprint(Edge edge, CellAddress startVertex)
                : this()
            {
                Contract.Requires(edge != null);

                this.startCellId = startVertex.CellId;
                this.startTrunkId = startVertex.TrunkId;
                this.endcellId = edge.EndVertex.CellId;
                this.endTrunkId = edge.EndVertex.TrunkId;
                this.edgeType = edge.EdgeType;
            }
        }
    }
}